﻿using System;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using OpenQuant.API;
using StockSharp.BusinessEntities;

namespace OpenQuant.Quik
{
    public partial class InstrumentsImport : Form
    {
        public InstrumentsImport()
        {
            InitializeComponent();
            UpdateInstrumentsList(null, null);
        }

        static SecurityProxy[] GetInstruments()
        {
            return Provider.QuikTrader.Securities.
                Where(s => (!string.IsNullOrEmpty(s.ShortName) &&
                        (!string.IsNullOrEmpty(s.Code)) &&
                        (!string.IsNullOrEmpty(s.Class)))).
                Select(s => new SecurityProxy
                    {
                        AltExchange = s.Class,
                        AltSource = "Quik",
                        AltSymbol = s.Code,
                        Currency = "RUR",
                        FullName = s.Name,
                        Margin = (double) s.MarginBuy,
                        Maturity = (s.ExpiryDate == null ? default(DateTime) : (DateTime) s.ExpiryDate),
                        PriceFormat = PriceFormat(s.Decimals),
                        ShortName = s.ShortName,
                        Symbol = s.Code,
                        Type = GetInstrumentType(s)
                    }).
                OrderBy(s => s.AltSymbol).ToArray();
        }

        static string PriceFormat(int decimals)
        {
            return string.Format("F{0}", (decimals >= 0) ? decimals : 2);
        }

        static InstrumentType GetInstrumentType(Security security)
        {
            var rst = InstrumentType.Stock;
            switch (security.Class)
            {
                case "SPBFUT":
                    rst = InstrumentType.Futures;
                    break;
                case "OPT":
                    rst = InstrumentType.Option;
                    break;
            }
            return rst;
        }

        void CheckAll(object sender, EventArgs e)
        {
            for (var i = 0; i < checkedListBoxQuik.Items.Count; i++)
                checkedListBoxQuik.SetItemChecked(i, true);
        }

        void UnCheckAll(object sender, EventArgs e)
        {
            for (var i = 0; i < checkedListBoxQuik.Items.Count; i++)
                checkedListBoxQuik.SetItemChecked(i, false);
        }

        void UpdateInstrumentsList(object sender, EventArgs e)
        {
            checkedListBoxQuik.Items.Clear();
            checkedListBoxQuik.Items.AddRange(GetInstruments());
            CheckAll(sender, e);
        }

        void Import(object sender, EventArgs e)
        {
            var cnt = 0;
            textBoxLog.Text = string.Empty;
            for (int i = 0; i < checkedListBoxQuik.Items.Count; i++)
            {
                try
                {
                    if (!checkedListBoxQuik.GetItemChecked(i)) continue;

                    var item = (SecurityProxy)checkedListBoxQuik.Items[i];
                    AppendLine(string.Format("Импорт инструмента: {0}...", item.Symbol));

                    var existsymbol = InstrumentManager.Instruments.Cast<Instrument>().
                                                        FirstOrDefault(ins => ins.Symbol == item.Symbol);
                    if (existsymbol != null)
                        throw new ArgumentException(
                            string.Format("Инструмент с Symbol = {0} уже присутствует в списке!", existsymbol.Symbol));

                    var instrument = new Instrument(item.Type, item.Symbol)
                        {
                            Currency = item.Currency,
                            Description = (item.Description ?? string.Empty),
                            Exchange = (item.Exchange ?? string.Empty),
                            Factor = item.Factor,
                            Group = (item.Group ?? string.Empty),
                            Margin = item.Margin,
                            Maturity = item.Maturity,
                            PriceFormat = item.PriceFormat,
                            PutCall = item.PutCall,
                            Sector = (item.Sector ?? string.Empty),
                            Strike = item.Strike,
                            TickSize = item.TickSize
                        };
                        
                    //Устанавливаем значения AltIDGroups у добавляемого инструмента (на момент разработки было возможно только через Reflection)
                    var altIdGroupList = typeof(AltIDGroupList).
                        GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] {typeof (Instrument)}, null)
                                                               .Invoke(new object[] {instrument});
                    instrument.GetType().GetProperty("AltIDGroups").SetValue(instrument, altIdGroupList, null);
                    instrument.AltIDGroups.Add("Quik");
                    instrument.AltIDGroups["Quik"].AltExchange = item.AltExchange;
                    instrument.AltIDGroups["Quik"].AltSource = item.AltSource;
                    instrument.AltIDGroups["Quik"].AltSymbol = item.AltSymbol;
                    cnt++;
                    AppendLine(string.Format("Инструмент: {0} успешно импортирован", item.Symbol));
                }
                catch (Exception ex)
                {
                    AppendLine(ex.Message);
                }
            }
            AppendLine(string.Format("Количетсво успешно импортированных инструментов = {0}", cnt));
            UpdateInstrumentsList(null, null);
        }

        void CheckedListBoxQuikSelectedIndexChanged(object sender, EventArgs e)
        {
            propertyGridInstr.SelectedObject = checkedListBoxQuik.SelectedItem;
        }

        void AppendLine(string text)
        {
            if (textBoxLog.Text == string.Empty)
                textBoxLog.AppendText(text);
            else
                textBoxLog.AppendText(Environment.NewLine + text);
        }
    }
}
